#include "EditWidget.h"
#include <QMouseEvent>

#include "Tool.h"
#include "MoveTool.h"
#include "CreateTool.h"

#include <QtDebug>

using namespace Editor;

Editor::VertexItem::VertexItem(Model::Vertex* vertex)
    : _vertex(vertex), _selected(false)
{
}

const Model::Vertex* Editor::VertexItem::vertex() const
{
    return _vertex;
}

Model::Vertex* Editor::VertexItem::vertex()
{
    return _vertex;
}

QRectF Editor::VertexItem::boundingRect() const
{
    return QRectF(vertex()->x() - 5, vertex()->y() - 5, 10, 10);
}

bool Editor::VertexItem::selected()
{
    return _selected;
}

void Editor::VertexItem::setSelected(bool s)
{
    _selected = s;
}

void Editor::VertexItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
    painter->setPen(selected()?Qt::red:Qt::black);
    painter->drawRect(vertex()->x() - 3, vertex()->y() - 3, 6, 6);
}

Editor::EdgeItem::EdgeItem(Model::Edge* edge)
    : _edge(edge), _selected(false)
{       }

Model::Edge* Editor::EdgeItem::edge()
{
    return _edge;
}

const Model::Edge* Editor::EdgeItem::edge() const
{
    return _edge;
}

QRectF Editor::EdgeItem::boundingRect() const
{
    return QRectF(edge()->start()->x(), edge()->start()->y(), 0, 0)
        .unite(QRectF(edge()->end()->x(), edge()->end()->y(), 0, 0));
}

bool Editor::EdgeItem::selected()
{
    return _selected;
}

void Editor::EdgeItem::setSelected(bool s)
{
    _selected = s;
}

void Editor::EdgeItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
    painter->setPen(selected()?Qt::red:Qt::black);
    painter->drawLine(QLine(edge()->start()->x(), edge()->start()->y(), edge()->end()->x(), edge()->end()->y()));
}

Editor::EditWidget::EditWidget() : background(0)
{
    using namespace Model;
    using namespace Editor;
    
    QGraphicsScene* scene = new QGraphicsScene(this);
    scene->setSceneRect(-100, -100, 200, 200);
    setScene(scene);
    setRenderHint(QPainter::Antialiasing);
    
    setMouseTracking(true);
    
    _mesh = new Model::Mesh();
}

void Editor::EditWidget::mouseMoveEvent(QMouseEvent *event)
{
    if(_tool)
        _tool->mouseMove(mapToScene(event->pos()));
}

void Editor::EditWidget::mousePressEvent(QMouseEvent *event)
{
    if(_tool)
        if(event->button() == 1)
            _tool->leftButtonPressed();
        else
            _tool->rightButtonPressed();
}

void Editor::EditWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if(_tool)
        if(event->button() == 1)
            _tool->leftButtonReleased();
        else
            _tool->rightButtonReleased();
}

void Editor::EditWidget::keyPressEvent(QKeyEvent* event)
{
    if(tool())
        tool()->keyPressEvent(event);
}

void Editor::EditWidget::setMesh(Model::Mesh* mesh)
{
    using namespace Model;
    _mesh = mesh;
    
    setScene(new QGraphicsScene(this));
    foreach(Vertex* v, *(mesh->vertexes()))
        addVertex(v);
    foreach(Model::Edge* e, *(mesh->edges()))
        addEdge(e);
}

Model::Mesh* Editor::EditWidget::mesh()
{
    return _mesh;
}

void Editor::EditWidget::setLights(std::list< Model::Light >* l)
{
  _lights = l;
}

std::list< Model::Light >& Editor::EditWidget::lights()
{
  return (*_lights);
}

Editor::VertexItem* Editor::EditWidget::getNearVertex(QPoint p)
{
    return getNearVertex(mapToScene(p));
}

Editor::VertexItem* Editor::EditWidget::getNearVertex(QPointF p)
{
    foreach(QGraphicsItem* i, this->items())
    {
        VertexItem* v = dynamic_cast<VertexItem*>(i);
        if(v) if(v->vertex()->isNear(p.x(), p.y()))
            return v;
    }
    
    return 0;
}

Editor::EdgeItem* Editor::EditWidget::getNearEdge(QPoint p)
{
    return getNearEdge(mapToScene(p));
}

Editor::EdgeItem* Editor::EditWidget::getNearEdge(QPointF p)
{
    foreach(QGraphicsItem* i, this->items())
    {
        EdgeItem* v = dynamic_cast<EdgeItem*>(i);
        if(v) if(v->edge()->isNear(p.x(), p.y()))
            return v;
    }
    
    return 0;
}


void Editor::EditWidget::setTool(Tool* tool)
{
    _tool = tool;
}

Tool* Editor::EditWidget::tool()
{
    return _tool;
}

void Editor::EditWidget::updateScene()
{
    scene()->update();
}

void Editor::EditWidget::setBackgroundImage(const QString& url)
{
    background = scene()->addPixmap(QPixmap(url));
    background->setPos(-(background->boundingRect().width()/2), -(background->boundingRect().height()/2));
    background->setZValue(-1);
}

Editor::VertexItem* Editor::EditWidget::addVertex(QPointF coords)
{
    return addVertex(new Model::Vertex(coords.x(), coords.y()));
}

Editor::VertexItem* Editor::EditWidget::addVertex(Model::Vertex* vertex)
{
    mesh()->vertexes()->append(vertex);
    VertexItem* item = new VertexItem(vertex);
    scene()->addItem(item);
    return item;
}

Editor::EdgeItem* Editor::EditWidget::addEdge(Model::Vertex* start, Model::Vertex* end)
{
    return addEdge(new Model::Edge(start, end));
}

Editor::EdgeItem* Editor::EditWidget::addEdge(Model::Edge* edge)
{
    mesh()->edges()->append(edge);
    EdgeItem* item = new EdgeItem(edge);
    scene()->addItem(item);
    edges.append(item);
    return item;
}

void Editor::EditWidget::removeVertex(Editor::VertexItem* item)
{
    scene()->removeItem(item);
    Model::Vertex *v = item->vertex();
    
    foreach(EdgeItem* edge, edges)
        if(edge->edge()->hasEnd(v))
            removeEdge(edge);
    
    mesh()->vertexes()->removeOne(v);
    delete v;
    delete item;
}

void Editor::EditWidget::removeEdge(Editor::EdgeItem* item)
{
    scene()->removeItem(item);
    mesh()->edges()->removeOne(item->edge());
    edges.removeOne(item);
    delete item->edge();
    delete item;
}
